package com.woniuxy.juc.reentrant;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.locks.LockSupport;

/**
 * <P> @Author: ideaAdmin
 * <P> TODO: Class
 * <P> TODO: 同步模式之顺序控制 顺序打印 (a,b,c)
 * <P> Date: 2022/4/8:8:48
 * <P> Description:
 */
@Slf4j(topic = "c.ObjectLoopPrint")
@SuppressWarnings(value = "all")
public class ObjectLoopPrint {

    /**
     * TODO t2是否运行过
     */
    static boolean t2Runned = false;

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            while (!t2Runned) {
                LockSupport.park();
                log.debug("1");
            }

        }, "t1");

        Thread t2 = new Thread(() -> {
            log.debug("2");
            t2Runned = true;
            LockSupport.unpark(t1);
        }, "t2");

        WaitNotify waitNotify = new WaitNotify(1, 5);

        for (int i = 0; i < 3; i++) {
            int num = i;
            new Thread(() -> {
                log.debug("i:{},num:{}", num, (num + 2) % 3 == 0 ? 3 : (num + 2) % 3);
                while (true) {

                    waitNotify.print(num + 1 + "", num + 1, (num + 2) % 3 == 0 ? 3 : (num + 2) % 3);
                }
            }).start();
        }


    }
}

/***
 * TODO: 输出内容 等待标记 下一个标记
 *          a    1          2
 *          b    2          3
 *          c    3          1
 **/
@Data
@NoArgsConstructor
@AllArgsConstructor
class WaitNotify {
    /**
     * TODO 等待标记
     */

    private int flag;

    /**
     * TODO 循环次数
     */
    private int loopNumber;

    public void print(String str, int waitFlag, int nextFlag) {
        for (int i = 0; i < loopNumber; i++) {
            synchronized (this) {
                while (flag != waitFlag) {
                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(str);
                flag = nextFlag;
                this.notifyAll();
            }
        }
    }

}
